package cmd

import (
	"fmt"
	"gitee.com/codexplus/yum-downloader/common"
	"regexp"
	"strings"
	"sync"

	"github.com/panjf2000/ants/v2"
	"github.com/spf13/cobra"
)

// syncCmd represents the sync command
var syncCmd = &cobra.Command{
	Use:   "sync",
	Short: "Synchronize RPM packages to the local.",
	Long:  ``,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println(fmt.Sprintf("Store: %s", AppConfig.Yum.StoreDir))
		fmt.Println(fmt.Sprintf("Thread Size: %d", AppConfig.Yum.ThreadNum))

		// defer ants.Release()

		var wg sync.WaitGroup

		p, _ := ants.NewPoolWithFunc(AppConfig.Yum.ThreadNum, func(i interface{}) {
			err := common.DownloadFile(i.(*common.DownItem))

			if err != nil {
				fmt.Println(fmt.Sprintf("ERROR: %s", err.Error()))
			}

			wg.Done()
		})

		defer p.Release()

		re := regexp.MustCompile("[-,]+")

		for _, v1 := range AppConfig.Yum.Repos {
			if !v1.Enabled {
				continue
			}

			releasevers := re.Split(v1.Releasever, -1)

			for _, el := range releasevers {
				repoBaseUrl := strings.ReplaceAll(strings.ReplaceAll(v1.Url, "{version}", v1.Version), "{releasever}", el)
				dirPath := strings.ReplaceAll(strings.ReplaceAll(v1.Dir, "{version}", v1.Version), "{releasever}", el)
				storeDir := fmt.Sprintf("%s/%s", AppConfig.Yum.StoreDir, dirPath)

				proxyUrl := ""

				if v1.UseProxy {
					proxyUrl = AppConfig.Yum.Proxy
				}

				// fmt.Println(fmt.Sprintf("Url: %s", repoBaseUrl))
				// fmt.Println(fmt.Sprintf("Dir: %s", dirPath))

				// Submit tasks one by one.
				err := common.PackagesIter(repoBaseUrl, proxyUrl, func(pack common.Package) {
					wg.Add(1)

					// fmt.Printf("%p\n", &pack)

					if len(v1.Packages) == 0 || (len(v1.Packages) > 0 && common.Contains(v1.Packages, pack.Name)) {
						_ = p.Invoke(&common.DownItem{ProxyUrl: AppConfig.Yum.Proxy, StoreDir: storeDir, RepoUrl: repoBaseUrl, Package: pack, RepoItem: v1})
					}
				})

				if err != nil {
					fmt.Println(fmt.Sprintf("ERR: %s", err.Error()))
				}
			}
		}

		wg.Wait()
	},
}

func init() {
	rootCmd.AddCommand(syncCmd)

	syncCmd.Flags().Bool("help", false, "Show help.")

	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// syncCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// syncCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
